package cn.eastseven.demo.netty.client;

import java.util.concurrent.TimeUnit;

import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.ScheduledFuture;

import org.springframework.stereotype.Component;

import cn.eastseven.demo.netty.common.Header;
import cn.eastseven.demo.netty.common.MessageType;
import cn.eastseven.demo.netty.common.NettyMessage;

@Component
@Sharable
public class HeartBeatReqHandler extends ChannelHandlerAdapter {

	private volatile ScheduledFuture<?> heartBeat;
	
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		NettyMessage message = (NettyMessage) msg;
		if(message.getHeader() != null && message.getHeader().getType() == MessageType.LOGIN_RESP) {
			long initialDelay = 0L;
			long period = 5*60*1000L;
			heartBeat = ctx.executor().scheduleAtFixedRate(new HeartBeatTask(ctx), initialDelay, period, TimeUnit.MILLISECONDS);
		} else if(message.getHeader() != null && message.getHeader().getType() == MessageType.HEARTBEAT_RESP) {
			
			System.out.println("client receive server heart beat msg: ===> " + message);
			
		} else {
			ctx.fireChannelRead(msg);
		}
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		if(heartBeat != null) {
			heartBeat.cancel(true);
			heartBeat = null;
		}
		ctx.fireExceptionCaught(cause);
	}
	
	private class HeartBeatTask implements Runnable {
		private final ChannelHandlerContext ctx;
		
		public HeartBeatTask(final ChannelHandlerContext ctx) {
			this.ctx = ctx;
		}
		
		public void run() {
			NettyMessage heartBeat = buildHeartBeat();
			System.out.println("Client send heart beat msg to server: ---> " + heartBeat);
			ctx.writeAndFlush(heartBeat);
		}
		
		private NettyMessage buildHeartBeat() {
			NettyMessage msg = new NettyMessage();
			Header header = new Header();
			header.setType(MessageType.HEARTBEAT_REQ);
			msg.setHeader(header);
			return msg;
		}
	}
}
